這個章節我們要把原本使用 Controller-View 的感激筆記頁面一步一步的改成 LiveView 版本,並加上一些新功能。
通常 LiveView 也是使用 RESTful 風格的路徑設定,所以通常在這邊的 note index 頁面會一樣用 /notes,但是在這篇教學一方面是想保留原本的 Controller-View 版本,另一方面是這個站的主要功能只有感激筆記,所以在這邊用 / 來取代 /notes,之後加上的新增頁面也會依照這個模式改為 /new。
scope "/", GratitudeWeb do
pipe_through :browser
# 將原本的首頁用我們即將建立的 Index 取代
live "/", NoteLive.Index, :index
# 舊的 Controller-View 版本
resources "/notes", NoteController, except: [:show]
live "/demo", DemoLive
end
路徑設定好後在 lib/gratitude_web/live/note_live/index.ex 建立一個 NoteLive.Index LiveView module
defmodule GratitudeWeb.NoteLive.Index do
use GratitudeWeb, :live_view
alias Gratitude.Notes
def mount(params, session, socket) do
notes = Notes.list_notes()
{:ok, assign(socket, notes: notes)}
end
def render(assigns) do
~H"""
<.header>感激筆記 LiveView 版</.header>
<.table id="notes" rows={@notes}>
<:col :let={note} label="ID"><%= note.id %></:col>
<:col :let={note} label="內容"><%= note.content %></:col>
</.table>
"""
end
end

可以注意到跟上一個 LiveView 頁面 DemoLive 相比,我們使用NoteLive.Index 來作為模組名稱,且檔案的位置也是 lib/gratitude_web/live/note_live/index.ex,雖然這次的範例只會有一個 LiveView 頁面,但是如果有多個頁面的話,可以把相關的頁面與共用 component 放在同一個資料夾下,如果有顯示單個 note 的頁面需求,就會有另一個 NoteLive.Show 的模組,並且放在 lib/gratitude_web/live/note_live/show.ex。
在 DemoLive 的 live 函式沒有像這次的 NoteLive.Index 一樣後面多加一個參數 :index,
我們先來看看 live 函式的定義
live(path, live_view, action \\ nil, opts \\ [])
在 DemoLive 的時候,我們忽略了第三個 action 讓它使用預設值 nil ,由於我們的 DemoLive 功能相當少所以不需要為他特別指定 action。
如果有多個路徑要用同一個 LiveView 通常會用 action 來區分,
例如之後我們會需要新增 note 的路徑 (/new),又想要用同一個 LiveView 來處理的話,就會在 Router 裡面使用 action 來區分:
live "/", NoteLive.Index, :index
live "/new", NoteLive.Index, :new
這樣一來,在 LiveView Module 裡我們可以在 assigns map 使用 live_action 得到該值,例如:
def mount(params, session, socket) do
case socket.assigns.live_action do
:index -> # 如果是 index 頁面要做的事
:new -> # 如果是 new 頁面要做的事
end
{:ok, socket}
end
或是在 heex template 上判斷依照不同的 action 來顯示不同的內容:
<.header>
<%= if @live_action == :index do %>
列出所有的感激筆記
<% else %>
新增感激筆記
<% end %>
</.header>